<?php

class FormBuilder_Children
{
	static private $index   = array();
	static private $objects = array();

#------------------------------------------------------------------------------

	/**
	 * Find if the name is within the index and if so return its key.
	 * Used by all functions.
	 *
	 * @param string $name
	 * @return bool|string False if not found, string if found.
	 */
	static private function _exists ($name)
	{
		return isset(self::$index[$name]) ? self::$index[$name] : false;
	}

	/**
	 * Just like the _exists but returns true if the key is found.
	 *
	 * @see Form_Children::_exists
	 * @return bool
	 */
	static function exists ($name)
	{
		return self::_exists($name) === false ? false : true;
	}

#------------------------------------------------------------------------------

	/**
	 * Add an element to the index for later calling and processing.
	 *
	 * @param string	$name		The name of the element. Will be used to track the object.
	 * @param object	$object		The meat, store the instance of the object here.
	 * @param bool		$overwrite	Should the function overwirte an object of the same name?
	 *
	 * @return bool
	 */
	static function add ($name, $object, $overwrite = false)
	{
		$key = self::_exists($name);
		if ($key !== false && $overwrite === false) {
			$error = 'Cannot overwrite object unless explicitly told to do so by passing true.';

			throw new FormBuilder_Exception($error, 555);
			return false;
		}

		if ($key === false) {

			# Returns a string that is unique for each object and is always the same for the same object. 
			# ref: http://www.php.net/manual/en/function.spl-object-hash.php
			$key = spl_object_hash($object);

		}

		self::$index[$name]  = $key;
		self::$objects[$key] = $object;

		return true;
	}

#------------------------------------------------------------------------------

	/**
	 * Just as it says, remove a child from the index.
	 *
	 * @param string $name Element's name you will to remove.
	 * @return bool
	 *
	 * @internal Should I return an exception of false if the element doesn't exists?
	 */
	static function remove ($name)
	{
		$key = self::_exists($name);
		if ($key !== false) {
			unset(self::$index[$name], self::$objects[$key]);
		}

		return true;
	}

#------------------------------------------------------------------------------

	/**
	 * If one wanted to edit the element during runtime but didn't save a ref
	 * to it you need to call it using this method.
	 *
	 * @param string $name Element you are seeking.
	 * @return bool|object  False on error, object on success.
	 */
	static function call ($name, $key = false)
	{
		$key = ($key) ? $name : self::_exists($name);
		if ($key === false || !isset(self::$objects[$key])) {
			$error = 'Trying to call an object that does not exists within the index.';

			throw new FormBuilder_Exception($error, 555);
			return false;
		}

		return self::$objects[$key];
	}

#------------------------------------------------------------------------------

	/**
	 * Did the element get a name change? we should update the index then.
	 *
	 * @param string $old Old name we are replacing.
	 * @param string $new New name we are replacing the old one with.
	 *
	 * @return bool
	 * @internal Should the old ref be kept and the new name added to the index?
	 */
	static function update ($old, $new)
	{
		$key = self::_exists($old);
		if ($key === false) {
			$error = 'The old name passed does not exists within the index, cannot update.';

			throw new FormBuilder_Exception($error, 555);
			return false;
		}

		unset(self::$index[$old]);
		self::$index[$new] = $key;
		return true;
	}

#------------------------------------------------------------------------------

	static function retriveIndex ()
	{
		return self::$index;
	}

	static function retriveObjects ()
	{
		return self::$objects;
	}
}

